package org.flexharmony.eclipse.properties.classinclusion;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
import org.flexharmony.eclipse.HarmonyLogger;
import org.flexharmony.eclipse.HarmonyPlugin;
import org.flexharmony.eclipse.domain.ExclusionFilter;
import org.flexharmony.eclipse.domain.IncludedSourceFolder;
import org.flexharmony.eclipse.domain.InclusionFilter;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

public class IncludedSourceFolderMarshaller
{
  static public final QualifiedName INCUSION_FOLDERS_QNAME 
      = new QualifiedName(HarmonyPlugin.PLUGIN_ID, "INCUSION_FOLDERS");

  static public List<IncludedSourceFolder> unmarshall(IProject project) throws CoreException
  {
    List<IncludedSourceFolder> folders = new ArrayList<IncludedSourceFolder>();
    String inclusionFoldersXml = project.getPersistentProperty(INCUSION_FOLDERS_QNAME);
    
    if ((inclusionFoldersXml != null) && (inclusionFoldersXml.trim().length() > 0))
    {
      try
      {
        SAXBuilder builder = new SAXBuilder();
        Reader in = new StringReader(inclusionFoldersXml);
        Document document = builder.build(in);
        Element root = document.getRootElement();
        
        List<Element> sourceFolderElements = root.getChildren("SourceFolder");
        for (Element sourceFolderElement : sourceFolderElements)
        {
          String path = sourceFolderElement.getChild("Path").getText();
          IPath ipath = new Path(path);
          
          IncludedSourceFolder folder = new IncludedSourceFolder(ipath);
          
          Element includedFilterElement = sourceFolderElement.getChild("IncludedElement");
          List<Element> includedPatternElements = includedFilterElement.getChildren("Pattern");
          List<String> includedPatterns = new ArrayList<String>();
          
          for (Element includedPatternElement : includedPatternElements)
          {
            includedPatterns.add(includedPatternElement.getText());
          }
          
          InclusionFilter includedFilter = new InclusionFilter(includedPatterns, folder);
          folder.setIncludedFilter(includedFilter);
  
          Element excludedFilterElement = sourceFolderElement.getChild("ExcludedElement");
          List<Element> excludedPatternElements = excludedFilterElement.getChildren("Pattern");
          List<String> excludedPatterns = new ArrayList<String>();
          
          for (Element excludedPatternElement : excludedPatternElements)
          {
            excludedPatterns.add(excludedPatternElement.getText());
          }
          
          ExclusionFilter excludedFilter = new ExclusionFilter(excludedPatterns, folder);
          folder.setExcludedFilter(excludedFilter);
          
          folders.add(folder);
        }
      }
      catch (Exception exc)
      {
        HarmonyLogger.logError("Unable to retrieve inclusion folders xml property.", exc);
        exc.printStackTrace();
        project.setPersistentProperty(INCUSION_FOLDERS_QNAME, null);
      }
    }
    
    return folders;
  }
  
  static public void save(List<IncludedSourceFolder> folders, IProject project) throws CoreException
  {
    if ((folders == null) || (folders.size() == 0))
    {
      project.setPersistentProperty(INCUSION_FOLDERS_QNAME, null);
    }
    else
    {
      Element rootElement = new Element("InclusionFolders");
      for (IncludedSourceFolder folder : folders)
      {
        Element folderElement = new Element("SourceFolder");
        rootElement.addContent(folderElement);
        
        Element pathElement = new Element("Path");
        pathElement.setText(folder.folderPath.toString());
        folderElement.addContent(pathElement);
        
        Element includedElement = new Element("IncludedElement");
        folderElement.addContent(includedElement);
        
        List<String> includedPatterns = folder.getIncludedFilter().patterns;
        for (String includedPattern : includedPatterns)
        {
          Element patternElement = new Element("Pattern");
          includedElement.addContent(patternElement);
          patternElement.setText(includedPattern);
        }

        Element excludedElement = new Element("ExcludedElement");
        folderElement.addContent(excludedElement);
        
        List<String> excludedPatterns = folder.getExcludedFilter().patterns;
        for (String excludedPattern : excludedPatterns)
        {
          Element patternElement = new Element("Pattern");
          excludedElement.addContent(patternElement);
          patternElement.setText(excludedPattern);
        }
      }
      
      Document document = new Document(rootElement);
      XMLOutputter serializer = new XMLOutputter();
      StringWriter writer = new StringWriter();
      try
      {
        serializer.output(document, writer);
        String xml = writer.toString();
        project.setPersistentProperty(INCUSION_FOLDERS_QNAME, xml);
      }
      catch (IOException ioexc)
      {
        HarmonyLogger.logError("Unable to save inclusion folder xml property due to io exception", ioexc);
        ioexc.printStackTrace();
      }
    }
  }
}
